package com.xiaoyu.awakening.ai.evaluation.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.xiaoyu.awakening.ai.evaluation.config.EvalConfigProperties;
import com.xiaoyu.awakening.ai.evaluation.dto.CreateSingleEvalTaskDTO;
import com.xiaoyu.awakening.ai.evaluation.dto.EvalDataSetGenerateContext;
import com.xiaoyu.awakening.ai.evaluation.dto.EvalQaPairDTO;
import com.xiaoyu.awakening.ai.evaluation.service.IAwkEvalDataSetService;
import jakarta.annotation.Resource;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.converter.BeanOutputConverter;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * DefaultEvalDataSetServiceImpl
 *
 * @author wangxiaoyu
 * @date 2025/8/20 16:54
 * @since v1.0
 */
@Service
@Log4j2
public abstract class BaseEvalDataSetServiceImpl implements IAwkEvalDataSetService {
    @Resource
    public ChatClient datasetGenerateAgent;
    private final static BeanOutputConverter<List<EvalQaPairDTO>> CONVERTER = new BeanOutputConverter<>(new ParameterizedTypeReference<>() {
    });

    @Resource
    private EvalConfigProperties evalConfigProperties;

    @Override
    public EvalDataSetGenerateContext generate(CreateSingleEvalTaskDTO createSingleEvalTaskDTO) {
        // 拉取评测数据集
        List<String> docList = doLoadDocuments(createSingleEvalTaskDTO);
        if (CollectionUtil.isEmpty(docList)) {
            log.warn("加载评测数据集为空，请检查参数，repoId:{},fileList:{}", createSingleEvalTaskDTO.getDirId(), createSingleEvalTaskDTO.getFileIdList());
            throw new RuntimeException("加载评测数据集为空，请检查参数");
        }
        // 根据评测数据集生成标准问答对
        List<EvalQaPairDTO> qaPairList = doGenerateStandardQaPair(docList, createSingleEvalTaskDTO.getQaPairNum());
        if (CollectionUtil.isEmpty(qaPairList)) {
            log.warn("生成问答对为空，请重试");
            throw new RuntimeException("生成问答对为空，请重试");
        }
        // 执行RAG流程
        EvalDataSetGenerateContext evalDataSetGenerateContext = new EvalDataSetGenerateContext();
        evalDataSetGenerateContext.setTaskCode(createSingleEvalTaskDTO.getTaskCode());
        evalDataSetGenerateContext.setUserId(createSingleEvalTaskDTO.getUserId());
        evalDataSetGenerateContext.setCallbackUrl(evalConfigProperties.getCallBackUrl());
        evalDataSetGenerateContext.setQaPairDTOList(qaPairList);
        List<EvalDataSetGenerateContext.DataSetSample> dataSetSampleList = new ArrayList<>();
        qaPairList.forEach(qa -> {
            // 执行RAG流程
            try {
                EvalDataSetGenerateContext.DataSetSample dataSetSample = doRagFlow(qa.getQuestion(), createSingleEvalTaskDTO);
                if (Objects.nonNull(dataSetSample)) {
                    dataSetSample.setUserInput(qa.getQuestion());
                    dataSetSample.setReference(qa.getAnswer());
                    dataSetSampleList.add(dataSetSample);
                }
            } catch (Exception e) {
                log.error("执行RAG流程失败:question:{}", qa.getQuestion(), e);
            }
        });
        evalDataSetGenerateContext.setSamples(dataSetSampleList);
        // 组装评测样本
        return evalDataSetGenerateContext;
    }

    /**
     * doLoadDocuments
     *
     * @param createSingleEvalTaskDTO 评测任务创建参数
     * @return java.util.List<java.lang.String>
     * @author wangxiaoyu
     * @date 2025/8/20 17:17
     * @since v1.0
     */
    public abstract List<String> doLoadDocuments(CreateSingleEvalTaskDTO createSingleEvalTaskDTO);

    private List<EvalQaPairDTO> doGenerateStandardQaPair(List<String> docList, int qaPairNum) {
        List<EvalQaPairDTO> res = new ArrayList<>();
        //构建消息体
        StringBuilder text = new StringBuilder(String.format("帮我生成%d个标准的问答对，文档列表如下：", qaPairNum));
        text.append("\n");
        for (int i = 0; i < docList.size(); i++) {
            String prompt = String.format("文档%d：%s", i + 1, docList.get(i));
            text.append(prompt).append("\n");
        }
        Message msg = new UserMessage(text.toString());
        String qaJson = datasetGenerateAgent.prompt().messages(msg).call().content();
        if (StringUtils.isBlank(qaJson)) {
            log.warn("生成问答对失败:{}", text);
            return res;
        }
        try {
            res = CONVERTER.convert(qaJson);
        } catch (Exception e) {
            log.error("反序列化失败:{}", qaJson, e);
        }
        return res;
    }

    /**
     * doRagFlow
     *
     * @param userInput 用户问题
     * @return com.icourt.forge.eval.dto.EvalDataSetGenerateContext.DataSetSample
     * @author wangxiaoyu
     * @date 2025/8/20 17:18
     * @since v1.0
     */
    protected abstract EvalDataSetGenerateContext.DataSetSample doRagFlow(String userInput, CreateSingleEvalTaskDTO createSingleEvalTaskDTO);
}
